3.2: Testing your App
Contents:
- Introduction
- About testing
- Setting up testing
- Creating and running unit tests
- Related Practical
- Learn More
In this chapter you'll get an overview of Android testing, and about creating and running local unit tests in Android Studio with JUnit.
About testing
Even though you have an app that compiles and runs and looks the way you want it to on different devices, you must make sure that your app will behave the way you expect it to in every situation, especially as your app grows and changes. Even if you try to manually test your app every time you make a change — a tedious prospect at best — you might miss something or not anticipate what end users might do with your app to cause it to fail.
Writing and running tests is a critical part of the software development process. "Test-Driven Development" (TDD) is a popular software development philosophy that places tests at the core of all software development for an application or service.This does not negate the need for further testing, it merely gives you a solid baseline to work with.
Testing your code can help you catch issues early in development—when they are the least expensive to address — and improve the robustness of your code as your app gets larger and more complex. With tests in your code, you can exercise small portions of your app in isolation, and in an automatable and repeatable manner. Because….the code you write to test your app doesn't end up in the production version of your app; it lives only on your development machine, alongside your app's code in Android Studio.
Types of tests
Android supports several different kinds of tests and testing frameworks. Two basic forms of testing Android Studio supports are local unit tests and instrumented tests.
Local unit tests are tests that are compiled and run entirely on your local machine with the Java Virtual Machine (JVM). Use local unit tests to test the parts of your app (such as the internal logic) that do not need access to the Android framework or an Android device or emulator, or those for which you can create fake ("mock" or stub) objects that pretend to behave like the framework equivalents.
Instrumented tests are tests that run on an Android device or emulator. These tests have access to the Android framework and to Instrumentation information such as the app's Context. You can use instrumented tests for unit testing, user interface (UI) testing, or integration testing, making sure the components of your app interact correctly with other apps. Most commonly, you use instrumented tests for UI testing, which allows you to test that your app behaves correctly when a user interacts with your app's activities or enters a specific input.
For most forms of user interface testing, you use the Espresso framework, which allows you to write automated UI tests. You'll learn about instrumented tests and Espresso in a later chapter.
Unit Testing
Unit tests should be the fundamental tests in your app testing strategy. By creating and running unit tests against your code, you can verify that the logic of individual functional code areas or units is correct. Running unit tests after every build helps you catch and fix problems introduced by code changes to your app.
A unit test generally exercises the functionality of the smallest possible unit of code (which could be a method, class, or component) in a repeatable way. Create unit tests when you need to verify the logic of specific code in your app. For example, if you are unit testing a class, your test might check that the class is in the right state. For a method, you might test its behavior for different values of its parameters, especially null.Typically, the unit of code is tested in isolation; your test monitors changes to that unit only. A mocking framework such as Mockito can be used to isolate your unit from its dependencies.You can also write your unit tests for Android in JUnit 4, a common unit testing framework for Java code.
The Android Testing Support Library
The Android Testing Support Library provides the infrastructure and APIs for testing Android apps, including support for JUnit 4. With the testing support library you can build and run test code for your apps.
You may already have the Android Testing Support Library installed with Android Studio. To check for the Android Support Repository, follow these steps:
- In Android Studio choose Tools > Android > SDK Manager.
- Click the SDK Tools tab, and look for the Support Repository.
- If necessary, update or install the library.
The Android Testing Support Library classes are located under the android.support.test package. There are also older testing APIs in android.test. You should use the support libraries first, when given a choice between the support libraries and the older APIs, as the support libraries help build and distribute tests in a cleaner and more reliable fashion than directly coding against the API itself.
Setting up testing
To prepare your project for testing in Android Studio, you need to:
- Organize your tests in a source set.
- Configure your project's gradle dependencies to include testing-related APIs.
Android Studio source sets
Source sets are a collection of related code in your project that are for different build targets or other "flavors" of your app. When Android Studio creates your project, it creates three source sets for you:
- The main source set, for your app's code and resources.
- The test source set, for your app's local unit tests.
- The androidTest source set, for Android instrumented tests.
Source sets appear in the Android Studio Android view under the package name for your app. The main source set includes just the package name. The test and androidTest source sets have the package name followed by (test) or (androidTest), respectively.
These source sets correspond to folders in the src directory for your project. For example, the files for the test source set are located in src/test/java.
Configure Gradle for test dependencies
To use the unit testing APIs, you need to configure the dependencies for your project. The default gradle build file for your project includes some of these dependencies by default, but you may need to add more dependencies for additional testing features such as matching or mocking frameworks.
In your app's top-level build.gradle file, specify these libraries as dependencies. Note that the version numbers for these libraries may have changed. If Android Studio reports a newer library, update the number to reflect the current version.
dependencies {
// Required -- JUnit 4 framework
testCompile 'junit:junit:4.12'
// Optional -- hamcrest matchers
testCompile 'org.hamcrest:hamcrest-library:1.3'
// Optional -- Mockito framework
testCompile 'org.mockito:mockito-core:1.10.19'
}
After you add dependencies to your build.gradle file you may have to sync your project to continue. Click Sync Now in Android Studio when prompted.
Configure a test runner
A test runner is a library or set of tools that enables testing to occur and the results to be printed to a log. Your Android project has access to a basic JUnit test runner as part of the JUnit4 APIs. The Android test support library includes a test runner for instrumented and Espresso tests, AndroidJUnitRunner
, which also supports Junit 3 and 4.
This chapter only demonstrates the default runner for unit tests. To set AndroidJUnitRunner as the default test runner in your Gradle project, add the following dependency to your build.gradle file. There may already be dependencies in the defaultConfig section. If so, add the testInstrumentationRunner line to that section.
android {
defaultConfig {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}
Creating and running unit tests
Create your unit tests as a generic Java file using the JUnit 4 APIs, and store those tests in the test source set. Each Android Studio project template includes this source set and a sample Java test file called ExampleUnitTest.
Create a new test class
To create a new test class file, add a Java file to the test source set for your project. Test class files for unit testing are typically named for the class in your app that you are testing, with "Test" appended. For example, if your have a class called Calculator in your app, the class for your unit tests would be CalculatorTest.
To add a new test class file, use these steps:
- Expand the java folder and the folder for your app's test source set. The existing unit test class files are shown.
- Right-click on the test source set folder and select New > Java Class.
- Name the file and click OK.
Write your tests
Use JUnit 4 syntax and annotations to write your tests. For example, the test class shown below includes the following annotations:
- The @RunWith annotation indicates the test runner that should be used for the tests in this class.
- The @SmallTest annotation indicates that this is a small (and fast) test.
- The @Before annotation marks a method as being the set up for the test.
- The @Test annotation marks a method as an actual test.
For more information on JUnit Annotations, see the JUnit Reference documentation.
@RunWith(JUnit4.class)
@SmallTest
public class CalculatorTest {
private Calculator mCalculator;
// Set up the environment for testing
@Before
public void setUp() {
mCalculator = new Calculator();
}
// test for simple addition
@Test
public void addTwoNumbers() {
double resultAdd = mCalculator.add(1d, 1d);
assertThat(resultAdd, is(equalTo(2d)));
}
}
The addTwoNumbers() method is the only actual test. The key part of a unit test is the assertion, which is defined here by the assertThat() method. Assertions are expressions that must evaluate and result in a value of true for the test to pass. JUnit 4 provides a number of assertion methods, but assertThat() is the most flexible, as it allows for general-purpose comparison methods called matchers. The Hamcrest framework is commonly used for matchers ("Hamcrest" is an anagram for matchers). Hamcrest includes a large number of comparison methods as well as enabling you to write your own.
For more information on assertions, see the JUnit reference documentation for the Assert class. For more information on the hamcrest framework, see the Hamcrest Tutorial.
Note that the addTwoNumbers() method in this example includes only one assertion. The general rule for unit tests is to provide a separate test method for every individual assertion. Grouping more than one assertion into a single method can make your tests harder to debug if only one assertion fails, and obscures the tests that do succeed.
Run your tests
To run your local unit tests, use these steps:
- To run a single test, right-click that test method and select Run.
- To test all the methods in a test class, right-click the test file in the project view and select Run.
- To run all tests in a directory, right-click on the directory and select Run tests.
The project builds, if necessary, and the testing view appears at the bottom of the screen. If all the tests you ran are successful, the progress bar at the top of the view turns green. A status message in the footer also reports "Tests Passed."
Related Practical
The related exercises and practical documentation is in Android Developer Fundamentals: Practicals.
Learn More
- Best Practices for Testing
- Getting Started with Testing
- Building Local Unit Tests
- JUnit 4 Home Page
- JUnit 4 API Reference
- Mockito Home Page
- Android Testing Support - Testing Patterns (video)
- Android Testing Codelab
- Android Tools Protip: Test Size Annotations
- The Benefits of Using assertThat over other Assert Methods in Unit Tests